#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <pthread.h>

#define LEFT    30000000
#define RIGHT   30000200
#define THRNUM  (RIGHT-LEFT+1)

// 定义一个结构体，使用结构体的方式进行传递参数
struct data_st{
	int num;
};

// 需要定义在main上面，负责找不到，或者先声明
static void *calculate(void *p)
{
	int i, j, mark;
    i = ((struct data_st *)p)->num;

    mark = 1;
    for (j = 2; j < i/2; j++) {
        if (i % j == 0) {
            mark = 0;
            break;
        }
    }

    //sleep(1000);
    if (mark)
        printf("%d is a primer\n", i);

	// 退出的时候，将结构体指针传递出去，用于内存的释放
    pthread_exit(p);

}

int main(int argc, char **argv)
{
	int i, err;
	pthread_t tids[THRNUM];
	struct data_st *parma;
	void *ptr; // 定义一个指针，用于接收线程关闭后，返回出来的结构体指针

	for (i = LEFT; i <= RIGHT; ++i) {
		// 申请一块空间保存参数，这样，每个线程都会有一个参数的内存空间
		parma = malloc(sizeof(*parma));
		if(parma == NULL)
		{
			perror("malloc()");
			exit(1);
		}
		parma->num = i;
		// 传递申请的结构体指针地址
		err = pthread_create(tids + (i-LEFT), NULL, calculate, parma);
		if (err) {
            fprintf(stderr, "pthread_create(): %s\n", strerror(err));
            exit(1);
        }	
	}
	/*
	 * 考虑一个问题：线程最大能创建多少个？
	 * ulimit -a 查看当前系统限制
	 * 线程共用代码段，但是会创建自己的栈
	 * 在32位机器上，栈的大小与剩余的内存空间一起决定共可以创建线程的数量
	 * 在64位机器上，因为用户空间会很大，有128t，因此线程数量大小的是pid的数量和栈的大小共同决定。
	 * */
	for (i = LEFT; i <= RIGHT; ++i) {
        pthread_join(tids[i-LEFT], &ptr);
		// 收拾完成后，需要将线程退出结果中返回过来的结构体指针，进行内存回收
		free(ptr);
    }

	exit(0);
}
